package toolx

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"text/template"

	"gitee.com/workits/pkgs/httpx"
	"gitee.com/workits/pkgs/utilx"
	inf "github.com/fzdwx/infinite"
	"github.com/fzdwx/infinite/components"
	"github.com/fzdwx/infinite/components/spinner"
)

// ParseTemplate 解析模版
func ParseTemplate(src, dest string, params any) {
	content, err := utilx.ReadFileToString(src)
	if err != nil {
		panic(fmt.Sprintf("🙅文件%s生成失败", dest))
	}
	tpl := template.Must(template.New("").Parse(content))
	f, err := os.Create(dest)
	if err != nil {
		panic(fmt.Sprintf("🙅文件%s生成失败", dest))
	}
	defer func() {
		f.Close()
	}()
	if err := tpl.Execute(f, params); err != nil {
		panic(fmt.Sprintf("🙅文件%s生成失败", dest))
	}
}

// VerInfo 版本信息
type VerInfo struct {
	VBig   int
	VSmall int
	Ver    int
	TDir   string
	Meta   string
}

// DownloadTemplates 下载全局模版
func DownloadTemplates(force bool) {
	// 获取用户临时目录
	userHome, err := os.UserHomeDir()
	if err != nil {
		panic("🙅获取用户临时目录失败")
	}

	globalCacheDir := userHome + PS + ".workits"
	globalCacheTplDir := globalCacheDir + PS + "templates"
	oldVersion := ""
	if !utilx.FsIsExist(globalCacheDir) {
		// 创建目录
		if err := utilx.CreateMutiDir(globalCacheTplDir); err != nil {
			panic("🙅创建缓存目录失败")
		}
	} else {
		if !force {
			panic("🔔全局环境已经存在")
		} else {
			// 读取旧版本号
			oldVersion, err = utilx.ReadFileToString(globalCacheDir + PS + "version")
			if err != nil {
				panic("🙅读取本地版本信息失败")
			}
		}
	}

	// 获取版本信息
	vBytes, err := httpx.DownloadToBytes(TplRepo+"version", nil)
	if err != nil {
		panic("🙅获取远程版本信息失败")
	}
	// 比较版本号
	if oldVersion == string(vBytes) {
		panic("🔔已经是最新版本了")
	}
	verInfo, err := parseVersion(string(vBytes))
	if err != nil {
		panic("🙅解析远程版本信息失败")
	}

	// 下载模版文件
	_ = inf.NewSpinner(spinner.WithShape(components.Dot)).Display(func(spinner *spinner.Spinner) {
		label := "正在下载: "
		templates := remoteTemplates(verInfo.TDir)
		for _, tpl := range templates {
			spinner.Refresh(label + tpl)
			if err := httpx.DownloadToFile(TplRepo+verInfo.TDir+"/"+tpl, globalCacheTplDir+PS+tpl, nil); err != nil {
				panic(err)
			}
		}

		spinner.Finish("模版下载完成")
	})

	// 创建版本信息
	if err := utilx.CreateFile(globalCacheDir+PS+"version", []byte(verInfo.Meta)); err != nil {
		panic("🙅创建本地版本信息失败")
	}
}

// CopyTemplates 拷贝模版
func CopyTemplates(projName string, force bool) {
	// 获取用户临时目录
	userHome, err := os.UserHomeDir()
	if err != nil {
		panic("🙅获取用户临时目录失败")
	}

	// 全局环境
	globalCacheDir := userHome + PS + ".workits"
	globalCacheTplDir := globalCacheDir + PS + "templates"

	// 检查全局环境
	if !utilx.FsIsExist(globalCacheDir) {
		DownloadTemplates(force) // 全局环境不存在, 创建全局环境
	}

	// 不能覆盖一个非空目录
	if projName != "." && utilx.FsIsExist(projName) {
		panic(fmt.Sprintf("🔔%s不是一个空目录", projName))
	}

	// 创建项目目录(含缓存目录)
	projCacheDir := projName + PS + ".workits"
	projCacheTplDir := projCacheDir + PS + "templates"
	if utilx.FsIsExist(projCacheDir) && !force {
		panic("🔔项目环境已经存在")
	}
	if err := utilx.CreateMutiDir(projCacheTplDir); err != nil {
		panic("🙅项目环境目录创建失败")
	}

	// 拷贝模版&创建版本号
	tpls := localTemplates()
	for _, tpl := range tpls {
		if err := utilx.CopyFile(globalCacheTplDir+PS+tpl, projCacheTplDir+PS+tpl, force); err != nil {
			panic(fmt.Sprintf("🙅%s拷贝失败", tpl))
		}
	}
	if err := utilx.CopyFile(globalCacheDir+PS+"version", projCacheDir+PS+"version", force); err != nil {
		panic("🙅拷贝版本文件失败")
	}
}

// 获取远程文件列表
func remoteTemplates(ver string) []string {
	vBytes, err := httpx.DownloadToBytes(TplRepo+ver+"/.files", nil)
	if err != nil {
		panic("🙅获取远程文件信息错误")
	}
	tpls := strings.Split(string(vBytes), "\n")
	tpls = append(tpls, ".files")
	return tpls
}

// 获取模板文件列表
func localTemplates() []string {
	// 获取用户临时目录
	userHome, err := os.UserHomeDir()
	if err != nil {
		panic("🙅获取用户临时目录失败")
	}

	// 全局环境
	globalCacheTplDir := userHome + PS + ".workits" + PS + "templates"

	content, err := utilx.ReadFileToString(globalCacheTplDir + PS + ".files")
	if err != nil {
		panic("🙅获取模版列表失败")
	}

	return strings.Split(content, "\n")
}

// 解析版本
func parseVersion(ver string) (*VerInfo, error) {
	if len(ver) == 0 {
		return &VerInfo{0, 0, 0, "", ""}, nil
	}
	if len(ver) != 23 {
		return nil, fmt.Errorf("版本号错误")
	}

	var (
		verInfo VerInfo
		err     error
	)

	// 大版本号
	verInfo.VBig, err = strconv.Atoi(ver[:8])
	if err != nil {
		return nil, err
	}

	// 小版本号
	verInfo.VSmall, err = strconv.Atoi(ver[8:10])
	if err != nil {
		return nil, err
	}

	// 版本号
	verInfo.Ver, err = strconv.Atoi(fmt.Sprintf("%d%02d", verInfo.VBig, verInfo.VSmall))
	if err != nil {
		return nil, err
	}

	// 目录
	verInfo.TDir = ver[strings.Index(ver, "_")+1:]

	// 源数据
	verInfo.Meta = ver

	return &verInfo, nil
}
